package vsvm.gui.forms;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import vsvm.data.model.AbstractAttribute;
import vsvm.data.model.AbstractDataModel;
import vsvm.data.model.CategorialAttribute;
import vsvm.data.model.GenericDataModel;
import vsvm.data.model.NumericAttribute;
import vsvm.data.source.AbstractDataSource;
import vsvm.gui.Environment;

public class CreateDataModelDialog extends JDialog {

	private JPanel jContentPane = null;
	private JList lstAttributes = null;
	private JPanel pnlControls = null;
	private JPanel pnlButtons = null;
	private JPanel pnlAttribute = null;
	private JPanel pnlDataModel = null;
	private JPanel pnlModelParams = null;
	private JPanel pnlRawData = null;
	private JLabel lblType = null;
	private JLabel lblName = null;
	private JComboBox cmbType = null;
	private JTextField txtName = null;
	private JButton btnCreate = null;
	private JButton btnCancel = null;
	
	private AbstractDataSource dataSource = null;
	private ArrayList<AbstractAttribute> lst = null;
	private JLabel lblModelName = null;
	private JLabel lblClassAttribute = null;
	private JTextField txtModelName = null;
	private JComboBox cmbClassAttr = null;
	private JTextPane txtRawData = null;
	private class ListListener implements ListSelectionListener {
		public void valueChanged(ListSelectionEvent event) {
			if (!event.getValueIsAdjusting()) {
				Object sel = lstAttributes.getSelectedValue();
				updateAttributeInfo((AbstractAttribute)sel);
			}
		}
	}
	
	
	private void updateAttributeInfo(AbstractAttribute attr) {
		if (attr == null) return;
		txtName.setText(attr.getName());
		cmbType.setSelectedIndex(attr.getAttributeType()==AbstractAttribute.NUMERIC_TYPE?0:1);
	}

	
	/**
	 * This method initializes lstAttributes	
	 * 	
	 * @return javax.swing.JList	
	 */
	private JPanel getLstAttributes() {
		if (lstAttributes == null) {
			lstAttributes = new JList();
			lstAttributes.addListSelectionListener(new ListListener());
		}
		JScrollPane sp = new JScrollPane(lstAttributes);
		sp.setPreferredSize(new Dimension(200,200));
		JPanel pnlAttrs = new JPanel(new BorderLayout());
		pnlAttrs.add(sp, BorderLayout.CENTER);
		pnlAttrs.setBorder(new TitledBorder("Attributes"));

		return pnlAttrs;
	}

	/**
	 * This method initializes pnlControls	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPnlControls() {
		if (pnlControls == null) {
			pnlControls = new JPanel();
			pnlControls.setLayout(new BorderLayout());
			pnlControls.add(getPnlButtons(), java.awt.BorderLayout.SOUTH);
			pnlControls.add(getPnlAttribute(), java.awt.BorderLayout.NORTH);
			pnlControls.add(getPnlDataModel(), java.awt.BorderLayout.CENTER);
		}
		return pnlControls;
	}

	/**
	 * This method initializes pnlButtons	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPnlButtons() {
		if (pnlButtons == null) {
			FlowLayout flowLayout = new FlowLayout();
			flowLayout.setHgap(25);
			pnlButtons = new JPanel();
			pnlButtons.setLayout(flowLayout);
			pnlButtons.setPreferredSize(new java.awt.Dimension(40,40));
			pnlButtons.add(getBtnCreate(), null);
			pnlButtons.add(getBtnCancel(), null);
		}
		return pnlButtons;
	}

	/**
	 * This method initializes pnlAttribute	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPnlAttribute() {
		if (pnlAttribute == null) {
			GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
			gridBagConstraints3.fill = java.awt.GridBagConstraints.HORIZONTAL;
			gridBagConstraints3.gridy = 1;
			gridBagConstraints3.weightx = 1.0;
			gridBagConstraints3.insets = new java.awt.Insets(10,5,5,20);
			gridBagConstraints3.gridx = 1;
			GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
			gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
			gridBagConstraints2.gridy = 0;
			gridBagConstraints2.weightx = 1.0;
			gridBagConstraints2.insets = new java.awt.Insets(10,5,5,20);
			gridBagConstraints2.gridx = 1;
			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
			gridBagConstraints1.gridx = 0;
			gridBagConstraints1.insets = new java.awt.Insets(10,20,5,10);
			gridBagConstraints1.anchor = java.awt.GridBagConstraints.WEST;
			gridBagConstraints1.gridy = 1;
			lblName = new JLabel();
			lblName.setText("Name");
			GridBagConstraints gridBagConstraints = new GridBagConstraints();
			gridBagConstraints.gridx = 0;
			gridBagConstraints.insets = new java.awt.Insets(10,20,5,10);
			gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
			gridBagConstraints.gridy = 0;
			lblType = new JLabel();
			lblType.setText("Type");
			pnlAttribute = new JPanel();
			pnlAttribute.setLayout(new GridBagLayout());
			pnlAttribute.setPreferredSize(new java.awt.Dimension(100,100));
			pnlAttribute.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Attribute info", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
			pnlAttribute.add(lblType, gridBagConstraints);
			pnlAttribute.add(lblName, gridBagConstraints1);
			pnlAttribute.add(getCmbType(), gridBagConstraints2);
			pnlAttribute.add(getTxtName(), gridBagConstraints3);
		}
		return pnlAttribute;
	}

	/**
	 * This method initializes pnlDataModel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPnlDataModel() {
		if (pnlDataModel == null) {
			pnlDataModel = new JPanel();
			pnlDataModel.setLayout(new BorderLayout());
			pnlDataModel.add(getPnlModelParams(), BorderLayout.NORTH);
			pnlDataModel.add(getPnlRawData(), BorderLayout.CENTER);
		}
		return pnlDataModel;
	}
	
	private JPanel getPnlModelParams() {
		if (pnlModelParams == null) {
			GridBagConstraints gridBagConstraints7 = new GridBagConstraints();
			gridBagConstraints7.fill = java.awt.GridBagConstraints.HORIZONTAL;
			gridBagConstraints7.gridy = 1;
			gridBagConstraints7.weightx = 1.0;
			gridBagConstraints7.insets = new java.awt.Insets(10,5,5,20);
			gridBagConstraints7.anchor = java.awt.GridBagConstraints.WEST;
			gridBagConstraints7.gridx = 1;
			GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
			gridBagConstraints6.fill = java.awt.GridBagConstraints.HORIZONTAL;
			gridBagConstraints6.gridy = 0;
			gridBagConstraints6.weightx = 1.0;
			gridBagConstraints6.insets = new java.awt.Insets(10,5,5,20);
			gridBagConstraints6.anchor = java.awt.GridBagConstraints.WEST;
			gridBagConstraints6.gridx = 1;
			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
			gridBagConstraints5.gridx = 0;
			gridBagConstraints5.insets = new java.awt.Insets(10,20,5,10);
			gridBagConstraints5.anchor = java.awt.GridBagConstraints.WEST;
			gridBagConstraints5.gridy = 1;
			lblClassAttribute = new JLabel();
			lblClassAttribute.setText("Class attribute");
			GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
			gridBagConstraints4.gridx = 0;
			gridBagConstraints4.insets = new java.awt.Insets(10,20,5,10);
			gridBagConstraints4.anchor = java.awt.GridBagConstraints.WEST;
			gridBagConstraints4.gridy = 0;
			lblModelName = new JLabel();
			lblModelName.setText("Model name");
			pnlModelParams = new JPanel();
			pnlModelParams.setLayout(new GridBagLayout());
			pnlModelParams.setPreferredSize(new java.awt.Dimension(90,90));
			pnlModelParams.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Data model settings", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
			pnlModelParams.add(lblModelName, gridBagConstraints4);
			pnlModelParams.add(lblClassAttribute, gridBagConstraints5);
			pnlModelParams.add(getTxtModelName(), gridBagConstraints6);
			pnlModelParams.add(getCmbClassAttr(), gridBagConstraints7);
		}
		return pnlModelParams;		
	}
	
	private JPanel getPnlRawData() {
		if (pnlRawData == null) {
			pnlRawData = new JPanel();
			pnlRawData.setLayout(new BorderLayout());
			pnlRawData.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Raw data view", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
			pnlRawData.add(getTxtRawData(), java.awt.BorderLayout.CENTER);
		}
		return pnlRawData;	
	}

	/**
	 * This method initializes cmbType	
	 * 	
	 * @return javax.swing.JComboBox	
	 */
	private JComboBox getCmbType() {
		if (cmbType == null) {
			cmbType = new JComboBox();
			cmbType.addItem("Numeric");
			cmbType.addItem("Categorial");
			//cmbType.setEnabled(false);
			cmbType.addItemListener(new java.awt.event.ItemListener() {
				boolean in = false;
				public void itemStateChanged(java.awt.event.ItemEvent e) {
					if (in) return;
					in = true;
					int ix = lstAttributes.getSelectedIndex();
					
					if (ix >= 0) {
						String name = ((AbstractAttribute)lstAttributes.getSelectedValue()).getName();
						AbstractAttribute a = cmbType.getSelectedIndex()==0?new NumericAttribute(name):new CategorialAttribute(name); 
						lst.set(ix, a);
						loadAttributes();
						lstAttributes.setSelectedIndex(ix);
					}
					in = false;
				}
			});
		}
		return cmbType;
	}

	/**
	 * This method initializes txtName	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getTxtName() {
		if (txtName == null) {
			txtName = new JTextField();
			txtName.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					AbstractAttribute a = (AbstractAttribute)lstAttributes.getSelectedValue();
					if (a != null) {
						a.setName(txtName.getText());
						lstAttributes.invalidate();
					}
				}
			});
		}
		return txtName;
	}

	/**
	 * This method initializes btnCreate	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getBtnCreate() {
		if (btnCreate == null) {
			btnCreate = new JButton();
			btnCreate.setPreferredSize(new java.awt.Dimension(80,25));
			btnCreate.setText("Create");
			btnCreate.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					if (txtModelName.getText().trim().equals("")) {
						JOptionPane.showMessageDialog(CreateDataModelDialog.this, "Name cannot be empty.");
						return;						
					}
					
					AbstractDataModel dm = new GenericDataModel();
					dataSource.setAttributes(lst);
					dm.setName(txtModelName.getText());
					//dm.setAttributes(lst);
					try {
						dataSource.fill(dm, (AbstractAttribute)cmbClassAttr.getSelectedItem());
					} catch (Exception ex) {
						JOptionPane.showMessageDialog(CreateDataModelDialog.this, "Failed to create data model. Possible inconsistent attribute data.", "Error", JOptionPane.ERROR_MESSAGE);
						return;						
					}
					Environment.getEnvironment().getWorkspace().addDataModel(dm);
					dataSource.close();
					dispose();
				}
			});
		}
		return btnCreate;
	}

	/**
	 * This method initializes btnCancel	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getBtnCancel() {
		if (btnCancel == null) {
			btnCancel = new JButton();
			btnCancel.setPreferredSize(new java.awt.Dimension(80,25));
			btnCancel.setText("Cancel");
			btnCancel.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					dataSource.close();
					dispose();
				}
			});
		}
		return btnCancel;
	}

	/**
	 * This method initializes txtModelName	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getTxtModelName() {
		if (txtModelName == null) {
			txtModelName = new JTextField();
		}
		return txtModelName;
	}


	/**
	 * This method initializes cmbClassAttr	
	 * 	
	 * @return javax.swing.JComboBox	
	 */
	private JComboBox getCmbClassAttr() {
		if (cmbClassAttr == null) {
			cmbClassAttr = new JComboBox();
		}
		return cmbClassAttr;
	}


	class MyTextPane extends JTextPane
	  {
	    public boolean getScrollableTracksViewportWidth()
	    {
	      return false ;
	    }
	  }

	/**
	 * This method initializes txtRawData	
	 * 	
	 * @return javax.swing.JTextPane	
	 */
	private JScrollPane getTxtRawData() {
		if (txtRawData == null) {
			txtRawData = new MyTextPane();
			txtRawData.setEditable(false);
		}
		
		JScrollPane scroll = new JScrollPane(txtRawData);
		
		return scroll;
	}


	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}


	public CreateDataModelDialog(Frame parent, AbstractDataSource dataSource) {
		super(parent);
		this.dataSource = dataSource;
		initialize();
		setLocationRelativeTo(parent);
		
		loadData();
	}
	
	
	private void loadData() {
		if (!dataSource.open()) return;
		lst = dataSource.readAttributes();
		loadAttributes();
		txtRawData.setText(dataSource.getRawData());
		
	}
	
	private void loadAttributes() {
		DefaultListModel lstModel = new DefaultListModel();
		DefaultComboBoxModel cmbModel = new DefaultComboBoxModel();
		
		for (Iterator<AbstractAttribute> iter = lst.iterator(); iter.hasNext();) {
			Object obj = iter.next();
			lstModel.addElement(obj);
			cmbModel.addElement(obj);
		}
		
		lstAttributes.setModel(lstModel);
		cmbClassAttr.setModel(cmbModel);		
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(700, 500);
		this.setTitle("Create data model");
		this.setModal(true);
		this.setContentPane(getJContentPane());
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getLstAttributes(), java.awt.BorderLayout.WEST);
			jContentPane.add(getPnlControls(), java.awt.BorderLayout.CENTER);
		}
		return jContentPane;
	}

	public void setModelName(String name) {
		txtModelName.setText(name);
	}
}  //  @jve:decl-index=0:visual-constraint="10,10"
